#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.biz.helper.weixin;


import org.apache.commons.lang.StringUtils;
import org.springframework.util.ReflectionUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Created by well on 15/6/2.
 */
public class WeixinUtil {

    public static <T> T parse(String xml,Class<T> clz)throws Exception {
        T t = clz.newInstance();
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();


        Document document = db.parse(new ByteArrayInputStream(xml.getBytes()));
        NodeList list = document.getElementsByTagName("xml");
        final Set<String> fieldName = new HashSet<String>();
        Map<String,String> val = new HashMap<String,String>();
        ReflectionUtils.doWithFields(clz, new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                fieldName.add(field.getName());
            }
        });

        for (int i = 0; i < list.getLength(); i++) {
            Element element = (Element) list.item(i);
            for (String f : fieldName) {
                NodeList fnode = element.getElementsByTagName(f);
                if (fnode != null && fnode.getLength() > 0) {
                    String content = fnode.item(0).getFirstChild().getNodeValue();
                    val.put(f, content);
                }
            }
        }
        Set<Map.Entry<String, String>> entries = val.entrySet();
        for(Map.Entry en:entries) {
            Method declaredMethod = clz.getDeclaredMethod("set" + upperFirst(en.getKey().toString()), String.class);
            if(declaredMethod!= null){
                declaredMethod.invoke(t,en.getValue());
            }
        }

        return t;
    }


    public static Map<String,String> parse2Map(String xml)throws Exception {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();
        Document document = db.parse(new ByteArrayInputStream(xml.getBytes()));
        NodeList list = document.getElementsByTagName("xml");
        Map<String,String> val = new HashMap<String,String>();
        for (int i = 0; i < list.getLength(); i++) {
            Element element = (Element) list.item(i);
                NodeList fnode = element.getChildNodes();
                if (fnode != null && fnode.getLength() > 0) {
                    for(int j=0;j<fnode.getLength();++j) {
                        String content = fnode.item(j).getFirstChild().getNodeValue();
                        val.put(fnode.item(j).getNodeName(), content);
                    }
                }

        }

        return val;
    }


    public static String upperFirst(String param) {
        if (StringUtils.isBlank(param)) {
            return "";
        }
        if(param.length() == 1){
            return param.toUpperCase();
        }
        char c1 = param.charAt(0);
        return Character.toUpperCase(c1) + param.substring(1);
    }

    public static void main(String[] args){
        try {
            Map map = parse2Map("<xml><appid><![CDATA[wxdeed38bec2e25da2]]></appid><bank_type><![CDATA[CMB_CREDIT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[1245312502]]></mch_id><nonce_str><![CDATA[2015060314423031900010909001]]></nonce_str><openid><![CDATA[oEyC1uO2T-zGd9a2tb68_OyF8X1o]]></openid><out_trade_no><![CDATA[2015060314423031900010909001]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[E7B4803324D1C8FB0EF51FA20BC62140]]></sign><time_end><![CDATA[20150603144300]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[NATIVE]]></trade_type><transaction_id><![CDATA[1007160223201506030202596747]]></transaction_id></xml>");
            System.out.println(map.get("return_code"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
